﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using GC_VKMD.BusinessEntities.Vkontakte;
using GC_VKMD.MusicDownloader.Abstractions.Interfaces.Managers;

namespace GC_VKMD.MusicDownloader.Managers
{
	public class VKAudioFileManager : IVKAudioFileManager
	{
		#region Constants

		private const string AUDIO_FILE_NAME_TEMPLATE = "{0} - {1}.mp3";

		#endregion

		#region Variables

		private readonly IList<char> _invalidPathChars;

		private readonly IList<char> _invalidFileNameChars;

		#endregion

		#region Constructors

		public VKAudioFileManager()
		{
			_invalidPathChars = Path.GetInvalidPathChars().ToList();
			_invalidFileNameChars = Path.GetInvalidFileNameChars();
		}

		#endregion

		#region IVKAudioFileManager Members

		public bool DownloadFile(AudioTrack track, string folderPath, Action<string> successfulDownloadFileAction, Action<string> errorDownloadFileAction)
		{
			try
			{
				if (track == null || string.IsNullOrWhiteSpace(track.Url) || string.IsNullOrWhiteSpace(track.Title)
				    || string.IsNullOrWhiteSpace(track.Artist))
				{
					var message = string.Format("Некорректная информация о треке.");
					if (track != null)
						message = string.Concat(message, string.Format("Доступная информация: Url - {0}; Title - {1}; Artist - {2};",
							track.Url, track.Title, track.Artist));
					throw new ArgumentException(message);
				}

				if (string.IsNullOrWhiteSpace(folderPath) || !Directory.Exists(folderPath))
					throw new DirectoryNotFoundException(string.Format("Папка для сохранения треков не доступна. Путь к папке - {0}", folderPath));

				var fileName = CleanFileName(string.Format(AUDIO_FILE_NAME_TEMPLATE, track.Artist.Trim(), track.Title.Trim()));
				var filePath = CleanFilePath(Path.Combine(folderPath, fileName));

				if (File.Exists(filePath) && successfulDownloadFileAction != null)
					successfulDownloadFileAction(string.Format("Трек {0} уже был скачан ранее!", fileName));
				else
				{
					using (var Client = new WebClient())
					{
						Client.DownloadFile(track.Url, filePath);
					}

					successfulDownloadFileAction(string.Format("Трек {0} был успешно скачан!", fileName));
				}

				return true;
			}
			catch (Exception ex)
			{
				if (errorDownloadFileAction != null)
					errorDownloadFileAction(ex.Message);
				return false;
			}
		}

		public bool DownloadFiles(IEnumerable<AudioTrack> tracks, string folderPath, Action<string> successfulDownloadFileAction, Action<string> errorDownloadFileAction)
		{
			try
			{
				(tracks ?? new List<AudioTrack>())
					.ToList()
					.ForEach(t => DownloadFile(t, folderPath, successfulDownloadFileAction, errorDownloadFileAction));

				if (successfulDownloadFileAction != null)
					successfulDownloadFileAction(string.Format("Операция завершена!"));

				return true;
			}
			catch (Exception ex)
			{
				if (errorDownloadFileAction != null)
					errorDownloadFileAction(ex.Message);

				return false;
			}
		}

		public string CleanFilePath(string filePath)
		{
			return string.Join(" -",
				(filePath ?? string.Empty).Split(_invalidPathChars.ToArray(), StringSplitOptions.RemoveEmptyEntries));
		}

		public string CleanFileName(string fileName)
		{
			return string.Join(" -",
				(fileName ?? string.Empty).Split(_invalidFileNameChars.ToArray(), StringSplitOptions.RemoveEmptyEntries));
		}

		#endregion
	}
}
